﻿using HelixToolkit.Wpf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Media3D;

namespace QuickStart_Project_01.Model3Ds
{
    // 定义一个 3D UI 元素类，用于渲染带柱子和金属网的围栏
    public class FenceModel3D : UIElement3D
    {
        // 材质对象：柱子部分（postsModel），围网部分（fenceModel）
        GeometryModel3D postsModel = new GeometryModel3D();
        GeometryModel3D fenceModel = new GeometryModel3D();

        // 属性：柱子直径、高度、间距，以及金属网大小（用于决定网格纹理分段）
        public double PoleDiameter { get; set; } = 0.05;
        public double PoleHeight { get; set; } = 2;
        public double PoleDistance { get; set; } = 2;
        public double MeshSize { get; set; } = 0.06;

        #region 依赖属性（用于支持 XAML 绑定）

        // 围网贴图纹理（可以在 XAML 中设置贴图为钢丝网图像）
        public Brush FenceTexture
        {
            get { return (Brush)GetValue(FenceTextureProperty); }
            set { SetValue(FenceTextureProperty, value); }
        }
        public static readonly DependencyProperty FenceTextureProperty =
            DependencyProperty.Register(
                "FenceTexture", typeof(Brush), typeof(FenceModel3D),
                new PropertyMetadata(null, new PropertyChangedCallback((s, e) => (s as FenceModel3D).SetFenceTexture())));

        // 围栏的路径点集合（一个个 3D 坐标点，组成围栏的路径）
        public Point3DCollection Positions
        {
            get { return (Point3DCollection)GetValue(PositionsProperty); }
            set { SetValue(PositionsProperty, value); }
        }
        public static readonly DependencyProperty PositionsProperty =
            DependencyProperty.Register(
                "Positions", typeof(Point3DCollection), typeof(FenceModel3D),
                new PropertyMetadata(new Point3DCollection(), new PropertyChangedCallback((s, e) => (s as FenceModel3D).InitModel())));

        #endregion

        // 构造函数：初始化材质与模型
        public FenceModel3D()
        {
            // 设置柱子为半透明红色
            postsModel.Material = MaterialHelper.CreateMaterial(Colors.Red, 0.5);

            // 初始化整个围栏模型（柱子和围网）
            this.InitModel();

            // 将两个 GeometryModel3D 加入 Model3DGroup 中，并赋值给 Visual3DModel 显示
            Model3DGroup group = new Model3DGroup();
            group.Children.Add(postsModel);
            group.Children.Add(fenceModel);
            this.Visual3DModel = group;
        }

        // 设置围栏纹理贴图（前后材质都使用相同贴图）
        private void SetFenceTexture()
        {
            this.fenceModel.Material = this.FenceTexture != null
                ? new DiffuseMaterial(this.FenceTexture) { AmbientColor = Colors.White }
                : null;

            this.fenceModel.BackMaterial = this.FenceTexture != null
                ? new DiffuseMaterial(this.FenceTexture) { AmbientColor = Colors.White }
                : null;
        }

        // 初始化围栏模型（包括柱子和围网）
        private void InitModel()
        {
            // ===== 构建柱子部分 =====
            var post_builder = new MeshBuilder(false, false); // 不生成法线和纹理
            var points = DistributePoles(); // 根据路径分布柱子的位置
            foreach (var p in points)
            {
                var p2 = p + new Vector3D(0, 0, this.PoleHeight); // 柱子顶点
                post_builder.AddCylinder(p, p2, this.PoleDiameter, 40); // 添加圆柱形柱子
            }
            this.postsModel.Geometry = post_builder.ToMesh(); // 转换为几何体并赋值

            // ===== 构建围网部分 =====
            var fence_builder = new MeshBuilder(false, true); // 不生成法线，生成纹理坐标
            var w0 = 0d; // 用于累积纹理坐标的横向偏移
            for (int i = 0; i < this.Positions.Count - 1; i++)
            {
                var p0 = this.Positions[i];                        // 当前段起点
                var p1 = this.Positions[i + 1];                    // 当前段终点
                var p2 = p1 + new Vector3D(0, 0, this.PoleHeight); // 上端终点
                var p3 = p0 + new Vector3D(0, 0, this.PoleHeight); // 上端起点

                // 计算垂直和水平纹理坐标单位长度（影响贴图拉伸）
                var dh = this.PoleHeight / this.MeshSize;
                var dw = p0.DistanceTo(p1) / this.MeshSize;

                // 添加网格面片（一个四边形），带上纹理坐标
                fence_builder.AddQuad(
                    p0, p1, p2, p3,
                    new Point(w0, dh), new Point(w0 + dw, dh), new Point(w0 + dw, 0), new Point(w0, 0));

                w0 += dw; // 累加横向纹理坐标偏移
            }

            this.fenceModel.Geometry = fence_builder.ToMesh(); // 转换为几何体并赋值
        }

        // 根据围栏路径（Positions）等间距分布柱子
        private IEnumerable<Point3D> DistributePoles()
        {
            var l0 = 0d; // 当前段的起始总距离
            var x = PoleDistance; // 当前目标点相对起始点的距离

            for (int i = 0; i + 1 < this.Positions.Count; i++)
            {
                var p0 = this.Positions[i];
                var p1 = this.Positions[i + 1];
                var d = p0.DistanceTo(p1); // 当前段长度

                // 在当前段中按 PoleDistance 插入柱子
                while (x >= l0 && x < l0 + d)
                {
                    var f = (x - l0) / d; // 当前柱子在段中的线性比例
                    yield return p0 + ((p1 - p0) * f); // 插值计算柱子位置
                    x += PoleDistance;
                }

                l0 += d;

                // 可选逻辑：如果是最后一段末尾，补一个终点柱子（可保留或移除）
                if (i + 1 == this.Positions.Count)
                {
                    yield return p1;
                }
            }
        }
    }

}
